#ifndef _IP_PROTOCOL_H_
#define _IP_PROTOCOL_H_

#include "ip_config.h"
#include "cube_hal.h"

#define IOT_PORT   12888
#define AUTOCFG_PORT  12886
#define DHCPC_SERVER_PORT  67
#define DHCPC_CLIENT_PORT  68
#define TFTP_SERVER_INIT_PORT   69
#define TFTP_SERVER_CONN_PORT   1028

#define ETH_ADDR_LEN 6

#if BYTE_ORDER == 0x1234
#define HTONS(n) (n)
#define HTONL(n) (n)
#elif BYTE_ORDER == 0x3412

#define HTONS(n) ((((uint16_t)((n) & 0x00ff)) << 8) |   \
                  (((uint16_t)(n) & 0xff00) >> 8))

#define HTONL(n) ((((uint32_t)((n) & 0x000000ff)) << 24) | \
                  (((uint32_t)((n) & 0x0000ff00)) << 8) | \
                  (((uint32_t)((n) & 0x00ff0000)) >> 8) | \
                  (((n) & 0xff000000) >> 24))
#else
#error "endian not set"
#endif

#define htons HTONS
#define htonl HTONL

#define IPADDR(b1, b2, b3, b4)                  \
    (((uint32_t)(b1) << 24) |                             \
     ((uint32_t)(b2) << 16) |                             \
     ((uint32_t)(b3) << 8)  |                             \
     ((uint32_t)(b4)))

#define ETHTYPE_ARP 0x0806
#define ETHTYPE_IP  0x0800
#define ETHTYPE_IP6 0x86dd

typedef __packed struct _eth_hdr {
    uint8_t dhwaddr[ETH_ADDR_LEN];
    uint8_t shwaddr[ETH_ADDR_LEN];
    uint16_t type;
} eth_hdr_t;

#define ARP_REQUEST 1
#define ARP_REPLY   2

#define ARP_HWTYPE_ETH 1

typedef __packed struct _arp_hdr {
    uint16_t hwtype;
    uint16_t protocol;

    uint8_t hwlen;
    uint8_t protolen;
    uint16_t opcode;

    uint8_t shwaddr[ETH_ADDR_LEN];
    uint32_t sipaddr;
    uint8_t dhwaddr[ETH_ADDR_LEN];
    uint32_t dipaddr; 
} arp_hdr_t;

#define IP_PROTO_ICMP  1
#define IP_PROTO_TCP   6
#define IP_PROTO_UDP   17

typedef __packed struct _ip_hdr {
    uint8_t vhl;
    uint8_t tos;
    uint16_t len;
    
    uint16_t ipid;        
    uint16_t ipoffset;
    
    uint8_t ttl;
    uint8_t proto;
    uint16_t ipchksum;
    
    uint32_t sipaddr;
    uint32_t dipaddr;
} ip_hdr_t;

#define ICMP_ECHO                      8
#define ICMP_ECHO_REPLY                0

typedef __packed struct _icmp_hdr {
    uint8_t type, icode;
    uint16_t icmpchksum;
    uint16_t id, seqno;  
} icmp_hdr_t;

typedef __packed struct _udp_hdr {
    uint16_t sport, dport;
    uint16_t udplen, udpchksum;
} udp_hdr_t;

#define AUTOCFG_MAGIC 0x57696948

typedef __packed struct _autocfg_hdr {
    uint32_t magic;
    uint32_t serverip;
    uint16_t serverport;
} autocfg_hdr_t;

#endif // _IP_PROTOCOL_H_
